home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / jade / src / x11_keys.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  9KB  |  347 lines

  1. /* x11_keys.c -- Event translation for X11
  2.    Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
  3.  
  4.    This file is part of Jade.
  5.  
  6.    Jade is free software; you can redistribute it and/or modify it
  7.    under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    Jade is distributed in the hope that it will be useful, but
  12.    WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with Jade; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include "jade.h"
  21. #include "jade_protos.h"
  22.  
  23. #include <string.h>
  24. #include <X11/keysym.h>
  25. #include <X11/Xutil.h>
  26.  
  27. #ifdef SWAP_DELETE_KEYS
  28. # define XK_DELETE XK_BackSpace
  29. # define XK_BACKSPACE XK_Delete
  30. #else
  31. # define XK_DELETE XK_Delete
  32. # define XK_BACKSPACE XK_BackSpace
  33. #endif
  34.  
  35. _PR void translate_event(u_long *, u_long *, XEvent *);
  36. _PR int cook_key(void *, u_char *, int);
  37. _PR bool lookup_event(u_long *, u_long *, u_char *);
  38. _PR bool lookup_event_name(u_char *, u_long, u_long);
  39.  
  40. _PR u_long esc_code, esc_mods;
  41. u_long esc_code = XK_Escape, esc_mods = EV_TYPE_KEYBD;
  42.  
  43. static u_long
  44. translate_mods(u_long mods, unsigned int state)
  45. {
  46.     if(state & ShiftMask)
  47.     mods |= EV_MOD_SHIFT;
  48.     if(state & LockMask)
  49.     mods ^= EV_MOD_SHIFT;
  50.     if(state & ControlMask)
  51.     mods |= EV_MOD_CTRL;
  52.     if(state & Mod1Mask)
  53.     mods |= EV_MOD_MOD1;
  54.     if(state & Mod2Mask)
  55.     mods |= EV_MOD_MOD2;
  56.     if(state & Mod3Mask)
  57.     mods |= EV_MOD_MOD3;
  58.     if(state & Mod4Mask)
  59.     mods |= EV_MOD_MOD4;
  60.     if(state & Mod5Mask)
  61.     mods |= EV_MOD_MOD5;
  62.     if(state & Button1Mask)
  63.     mods |= EV_MOD_BUTTON1;
  64.     if(state & Button2Mask)
  65.     mods |= EV_MOD_BUTTON2;
  66.     if(state & Button3Mask)
  67.     mods |= EV_MOD_BUTTON3;
  68.     if(state & Button4Mask)
  69.     mods |= EV_MOD_BUTTON4;
  70.     if(state & Button5Mask)
  71.     mods |= EV_MOD_BUTTON5;
  72.     return(mods);
  73. }
  74.  
  75. void
  76. translate_event(u_long *code, u_long *mods, XEvent *xev)
  77. {
  78.     static Time LastClick;
  79.     switch(xev->type)
  80.     {
  81.     case KeyPress:
  82.     *mods = translate_mods(*mods, xev->xkey.state);
  83.     if(*mods & EV_MOD_SHIFT)
  84.     {
  85.         /* Some keys don't have keysym at index 1, if not treat it as
  86.            normal keysym shifted.  */
  87.         *code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 1);
  88.         if(*code == NoSymbol)
  89.         *code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 0);
  90.         else
  91.         *mods &= ~EV_MOD_SHIFT;
  92.     }
  93.     else
  94.         *code = XKeycodeToKeysym(x11_display, xev->xkey.keycode, 0);
  95.     if((*code != NoSymbol) && !IsModifierKey(*code))
  96.         *mods |= EV_TYPE_KEYBD;
  97.     break;
  98.     case ButtonPress:
  99.     if(xev->xbutton.time < (LastClick + DOUBLE_CLICK_TIME))
  100.         *code = EV_CODE_MOUSE_CLICK2;
  101.     else
  102.         *code = EV_CODE_MOUSE_CLICK1;
  103.     LastClick = xev->xbutton.time;
  104.     goto button;
  105.     break;
  106.     case ButtonRelease:
  107.     *code = EV_CODE_MOUSE_UP;
  108. button:
  109.     *mods = EV_TYPE_MOUSE
  110.         | translate_mods(*mods, xev->xbutton.state);
  111.     switch(xev->xbutton.button)
  112.     {
  113.     case Button1:
  114.         *mods |= EV_MOD_BUTTON1;
  115.         break;
  116.     case Button2:
  117.         *mods |= EV_MOD_BUTTON2;
  118.         break;
  119.     case Button3:
  120.         *mods |= EV_MOD_BUTTON3;
  121.         break;
  122.     case Button4:
  123.         *mods |= EV_MOD_BUTTON4;
  124.         break;
  125.     case Button5:
  126.         *mods |= EV_MOD_BUTTON5;
  127.         break;
  128.     }
  129.     break;
  130.     }
  131. }
  132.  
  133. int
  134. cook_key(void *event, u_char *buf, int buflen)
  135. {
  136.     XKeyEvent *xk = event;
  137.     KeySym ks;
  138.     return(XLookupString(xk, buf, buflen, &ks, NULL));
  139. }
  140.  
  141. /*
  142.  * Stuff to translate textual key descriptions into key codes
  143.  */
  144.  
  145. typedef struct
  146. {
  147.     u_char     *kd_Name;
  148.     u_long      kd_Mods;
  149.     u_long      kd_Code;
  150. } KeyDesc;
  151.  
  152. static const KeyDesc KeyDescr[] =
  153. {
  154.     "Shift",    EV_MOD_SHIFT, 0,
  155.     "SFT",      EV_MOD_SHIFT, 0,
  156.     "Ctrl",     EV_MOD_CTRL, 0,
  157.     "Control",  EV_MOD_CTRL, 0,
  158.     "CTL",      EV_MOD_CTRL, 0,
  159.     "Meta",     EV_MOD_META, 0,
  160.     "Mod1",     EV_MOD_MOD1, 0,
  161.     "Mod2",     EV_MOD_MOD2, 0,
  162.     "Amiga",    EV_MOD_MOD2, 0,
  163.     "Mod3",     EV_MOD_MOD3, 0,
  164.     "Mod4",     EV_MOD_MOD4, 0,
  165.     "LMB",      EV_MOD_LMB, 0,
  166.     "Button1",  EV_MOD_BUTTON1, 0,
  167.     "MMB",      EV_MOD_MMB, 0,
  168.     "Button2",  EV_MOD_BUTTON2, 0,
  169.     "RMB",      EV_MOD_RMB, 0,
  170.     "Button3",  EV_MOD_BUTTON3, 0,
  171.     "Button4",  EV_MOD_BUTTON4, 0,
  172.     "Button5",  EV_MOD_BUTTON5, 0,
  173.  
  174.     "SPC",      EV_TYPE_KEYBD, XK_space,
  175.     "Space",    EV_TYPE_KEYBD, XK_space,
  176.     "Spacebar", EV_TYPE_KEYBD, XK_space,
  177.     "TAB",      EV_TYPE_KEYBD, XK_Tab,
  178.     "RET",      EV_TYPE_KEYBD, XK_Return,
  179.     "Return",   EV_TYPE_KEYBD, XK_Return,
  180.     "ESC",      EV_TYPE_KEYBD, XK_Escape,
  181.     "Escape",   EV_TYPE_KEYBD, XK_Escape,
  182.     "BS",       EV_TYPE_KEYBD, XK_BACKSPACE,
  183.     "Backspace", EV_TYPE_KEYBD, XK_BACKSPACE,
  184.     "DEL",      EV_TYPE_KEYBD, XK_DELETE,
  185.     "Delete",   EV_TYPE_KEYBD, XK_DELETE,
  186.     "Help",     EV_TYPE_KEYBD, XK_Help,
  187.     "Up",       EV_TYPE_KEYBD, XK_Up,
  188.     "Down",     EV_TYPE_KEYBD, XK_Down,
  189.     "Right",    EV_TYPE_KEYBD, XK_Right,
  190.     "Left",     EV_TYPE_KEYBD, XK_Left,
  191.  
  192.     /* X defines lots of long names for these simple keys...  */
  193.     " ",        EV_TYPE_KEYBD, XK_space,
  194.     "!",        EV_TYPE_KEYBD, XK_exclam,
  195.     "\"",       EV_TYPE_KEYBD, XK_quotedbl,
  196.     "#",        EV_TYPE_KEYBD, XK_numbersign,
  197.     "$",        EV_TYPE_KEYBD, XK_dollar,
  198.     "%",        EV_TYPE_KEYBD, XK_percent,
  199.     "&",        EV_TYPE_KEYBD, XK_ampersand,
  200.     "'",        EV_TYPE_KEYBD, XK_quoteright,
  201.     "(",        EV_TYPE_KEYBD, XK_parenleft,
  202.     ")",        EV_TYPE_KEYBD, XK_parenright,
  203.     "*",        EV_TYPE_KEYBD, XK_asterisk,
  204.     "+",        EV_TYPE_KEYBD, XK_plus,
  205.     ",",        EV_TYPE_KEYBD, XK_comma,
  206.     "-",        EV_TYPE_KEYBD, XK_minus,
  207.     ".",        EV_TYPE_KEYBD, XK_period,
  208.     "/",        EV_TYPE_KEYBD, XK_slash,
  209.     ":",        EV_TYPE_KEYBD, XK_colon,
  210.     ";",        EV_TYPE_KEYBD, XK_semicolon,
  211.     "<",        EV_TYPE_KEYBD, XK_less,
  212.     "=",        EV_TYPE_KEYBD, XK_equal,
  213.     ">",        EV_TYPE_KEYBD, XK_greater,
  214.     "?",        EV_TYPE_KEYBD, XK_question,
  215.     "@",        EV_TYPE_KEYBD, XK_at,
  216.     "[",        EV_TYPE_KEYBD, XK_bracketleft,
  217.     "\\",       EV_TYPE_KEYBD, XK_backslash,
  218.     "]",        EV_TYPE_KEYBD, XK_bracketright,
  219.     "^",        EV_TYPE_KEYBD, XK_asciicircum,
  220.     "_",        EV_TYPE_KEYBD, XK_underscore,
  221.     "`",        EV_TYPE_KEYBD, XK_quoteleft,
  222.     "{",        EV_TYPE_KEYBD, XK_braceleft,
  223.     "|",        EV_TYPE_KEYBD, XK_bar,
  224.     "}",        EV_TYPE_KEYBD, XK_braceright,
  225.     "~",        EV_TYPE_KEYBD, XK_asciitilde,
  226.     "£",        EV_TYPE_KEYBD, XK_sterling,
  227.  
  228.     /* Mouse events */
  229.     "Click1",   EV_TYPE_MOUSE, EV_CODE_MOUSE_CLICK1,
  230.     "Click2",   EV_TYPE_MOUSE, EV_CODE_MOUSE_CLICK2,
  231.     "Off",      EV_TYPE_MOUSE, EV_CODE_MOUSE_UP,
  232.     "Move",     EV_TYPE_MOUSE, EV_CODE_MOUSE_MOVE,
  233.  
  234.     NULL, 0, 0
  235. };
  236.  
  237. /* Puts the integers defining the event described in DESC into CODE and
  238.    MODS.  */
  239. bool
  240. lookup_event(u_long *code, u_long *mods, u_char *desc)
  241. {
  242.     u_char *str = desc;
  243.     bool rc = TRUE;
  244.     *code = *mods = 0;
  245.     for(;;)
  246.     {
  247.     u_char buff[100];
  248.     u_char *tmp = buff;
  249.     u_char c = *str++;
  250.     const KeyDesc *kd = KeyDescr;
  251.     /* Get this one token.  The first character is read separately to
  252.        allow minus characters to be used to represent itself as well as
  253.        to terminate a token. */
  254.     if(c != 0)
  255.     {
  256.         *tmp++ = c;
  257.         while((c = *str) && (c != '-'))
  258.         {
  259.         *tmp++ = c;
  260.         str++;
  261.         }
  262.     }
  263.     else
  264.         goto error;
  265.     *tmp = 0;
  266.     if(*str)
  267.         str++;
  268.     while(kd->kd_Name)
  269.     {
  270.         if(!strcasecmp(kd->kd_Name, buff))
  271.         {
  272.         *mods |= kd->kd_Mods;
  273.         *code = kd->kd_Code;
  274.         if(*mods & EV_TYPE_MASK)
  275.             goto end;
  276.         break;
  277.         }
  278.         kd++;
  279.     }
  280.     if(!kd->kd_Name)
  281.     {
  282.         unsigned int ks;
  283.         if((ks = XStringToKeysym(buff)) != NoSymbol)
  284.         {
  285.         *mods |= EV_TYPE_KEYBD;
  286.         *code = ks;
  287.         goto end;
  288.         }
  289.         else
  290.         {
  291.         error:
  292.         cmd_signal(sym_bad_event_desc, LIST_1(string_dup(desc)));
  293.         rc = FALSE;
  294.         goto end;
  295.         }
  296.     }
  297.     }
  298. end:
  299.     return(rc);
  300. }
  301.  
  302. /* Constructs the name of the event defined by CODE and MODS in BUF.  */
  303. bool
  304. lookup_event_name(u_char *buf, u_long code, u_long mods)
  305. {
  306.     /* First resolve all modifiers */
  307.     u_long tmp_mods = mods & EV_MOD_MASK;
  308.     const KeyDesc *kd = KeyDescr;
  309.     u_char *name;
  310.     while(kd->kd_Name && (tmp_mods != 0))
  311.     {
  312.     if((tmp_mods & kd->kd_Mods) != 0)
  313.     {
  314.         tmp_mods &= ~kd->kd_Mods;
  315.         buf = stpcpy(buf, kd->kd_Name);
  316.         *buf++ = '-';
  317.     }
  318.     kd++;
  319.     }
  320.     if(tmp_mods != 0)
  321.     return(FALSE);
  322.     /* Now try to find the code in our lookup table */
  323.     tmp_mods = mods & EV_TYPE_MASK;
  324. #if 0
  325.     /* Since all modifiers are at the start of the table this is
  326.        unnecessary :-) */
  327.     kd = KeyDescr;
  328. #endif
  329.     while(kd->kd_Name)
  330.     {
  331.     if((kd->kd_Mods == tmp_mods) && (kd->kd_Code == code))
  332.     {
  333.         strcpy(buf, kd->kd_Name);
  334.         return(TRUE);
  335.     }
  336.     kd++;
  337.     }
  338.     /* Couldn't find it here; have to go to the window-system. */
  339.     name = XKeysymToString((KeySym)code);
  340.     if(name)
  341.     {
  342.     strcpy(buf, name);
  343.     return(TRUE);
  344.     }
  345.     return(FALSE);
  346. }
  347.